﻿
using System;
using System.Collections.Generic;

using Bootstrap5.Abstractions;

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;

namespace Bootstrap5;

/// <summary>
/// Represents a slideshow component for cycling through elements—images or slides of text.
/// </summary>
[CssClass("carousel slide")]
public class Carousel:BootstrapChildContentComponentBase
{
    /// <summary>
    /// Add the indicators to the carousel.
    /// </summary>
    [Parameter] public bool Indicators { get; set; }
    /// <summary>
    /// Adding in the previous and next controls. 
    /// </summary>
    [Parameter] public bool Controls { get; set; }
    /// <summary>
    /// Animate slides with a fade transition.
    /// </summary>
    [Parameter] [CssClass("carousel-fade")] public bool Fade { get; set; }
    /// <summary>
    ///  Set a unique idfor optional controls, especially if you’re using multiple carousels on a single page.
    /// </summary>
    [Parameter][HtmlProperty("id")]public string Id { get; set; }
    /// <summary>
    /// The amount of time to delay between automatically cycling an item. 
    /// If <c>null</c>, carousel will not automatically cycle.
    /// Default is 5000ms.
    /// </summary>
    [Parameter] [DataTrigger("interval")] public string Interval { get; set; }
    /// <summary>
    /// Whether the carousel should support left/right swipe interactions on touchscreen devices.
    /// Default is <c>true</c>.
    /// </summary>
    [Parameter] [DataTrigger("touch")] public bool? Touch { get; set; }
    /// <summary>
    /// Autoplays the carousel after the user manually cycles the first item. 
    /// If set <c>true</c>, autoplays the carousel on load.
    /// Default is <c>true</c>.
    /// </summary>
    [Parameter] [DataTriggerBoolean("ride", "carousel", FalseValue = "false")] public bool? AutoPlay { get; set; } = true;
    /// <summary>
    /// If set <c>true</c>, pauses the cycling of the carousel on mouseenter and resumes the cycling of the carousel on mouseleave. 
    /// If set <c>false</c>, hovering over the carousel won't pause it.
    /// Default is <c>true</c>.
    /// </summary>
    /// <remarks>
    /// On touch-enabled devices, when set <c>true</c>, cycling will pause on touchend (once the user finished interacting with the carousel) for two intervals, before automatically resuming. Note that this is in addition to the above mouse behavior.
    /// </remarks>
    [Parameter] [DataTriggerBoolean("pause","hover",FalseValue ="false")] public bool? PauseOnHover { get; set; }
    /// <summary>
    /// Whether the carousel should react to keyboard events. Default is <c>true</c>.
    /// </summary>
    [Parameter] [DataTrigger("keyboard")] public bool? Keyboard { get; set; }
    internal List<CarouselItem> Items { get; set; } = new List<CarouselItem>();

    public void AddItem(CarouselItem item)
    {
        if (item is null)
        {
            throw new ArgumentNullException(nameof(item));
        }
        Items.Add(item);

        StateHasChanged();
    }

    protected override void BuildRenderTree(RenderTreeBuilder builder)
    {
        builder.OpenElement(0, GetHtmlTagName());
        BuildCommonAttributes(builder);
        //builder.AddContent(100, cascading =>
        //{
        //    cascading.OpenComponent<Carousel>(0);
        //    cascading.AddAttribute(1,nameof(Carousel.ChildContent),(RenderFragment)content
        //    cascading.CloseComponent();
        //})
        this.CreateCascadingValueComponent<Carousel>(builder, content =>
        {
            BuildIndicator(content);
            BuildInnerItems(content);
            BuildControlButtons(content);
        });
        builder.CloseElement();
    }

    private void BuildControlButtons(RenderTreeBuilder builder)
    {
        if (!Controls)
        {
            return;
        }

        BuildButton(builder,"prev","Previous",300);
        BuildButton(builder, "next", "Next", 400);
        void BuildButton(RenderTreeBuilder builder,string name,string text,int sequence)
        {
            builder.OpenRegion(sequence);
            builder.OpenElement(0, "button");
            builder.AddAttribute(1, "type","button");
            builder.AddAttribute(2, "class", $"carousel-control-{name}");
            builder.AddAttribute(3, "data-bs-target", "#" + Id);
            builder.AddAttribute(4, "data-bs-slide", name);
            builder.AddContent(5, content =>
            {
                content.OpenElement(0, "span");
                content.AddAttribute(1, "class",$"carousel-control-{name}-icon");
                content.CloseElement();

                content.OpenElement(2, "span");
                content.AddAttribute(3, "class", $"visually-hidden");
                content.AddContent(4, text);
                content.CloseElement();
            });
            builder.CloseElement();
            builder.CloseRegion();
        }
    }

    private void BuildInnerItems(RenderTreeBuilder builder)
    {
        builder.OpenRegion(200);
        builder.OpenElement(0, "div");
        builder.AddAttribute(1, "class", "carousel-inner");
        builder.AddContent(2,  ChildContent);
        builder.CloseElement();
        builder.CloseRegion();
    }

    void BuildIndicator(RenderTreeBuilder builder)
    {
        if (!Indicators)
        {
            return;
        }
        builder.OpenRegion(100);
        builder.OpenElement(0, "div");
        builder.AddAttribute(1, "class", "carousel-indicators");
        builder.AddContent(2, indicator =>
        {
            for (int i = 0; i < Items.Count; i++)
            {
                var item = Items[i];
                var key = i;
                indicator.OpenElement(0, "button");
                indicator.SetKey(key);
                if (item.Active)
                {
                    indicator.AddAttribute(1, "class", "active");
                }
                indicator.AddAttribute(2, "data-bs-target", "#" + Id);
                indicator.AddAttribute(3, "data-bs-slide-to", i);
                indicator.CloseComponent();
            }
        });
        builder.CloseElement();
        builder.CloseRegion();
    }
}
